package mint.modules.generator.expression;

import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;

import org.antlr.runtime.tree.Tree;

import mint.modules.generator.Scope;
import mint.modules.symbol.Symbol;
import mint.modules.symbol.SymbolType;
import mint.modules.type.Type;
import mint.modules.type.TypeId;

public class CastExprNode extends Expression {
	private Type destinyType;
	private Expression unaryExpr;	
	private int line;
	private List<String> errors;

	public CastExprNode(Scope theParent, ExpressionType exprType, Tree castExprTree) {
		super(theParent, exprType);
		destinyType = Type.getTypeFromTree(castExprTree.getChild(0));
		unaryExpr = new UnaryExprNode(theParent, ExpressionType.Right, castExprTree.getChild(0));
		line = castExprTree.getLine();
		errors = new ArrayList<String>();
	}

	@Override
	public void testSemantic() {
		if (getExpressionType() == ExpressionType.Left || getExpressionType() == ExpressionType.RightLeft)
			errors.add(line + ": cast expression must be on the right side of a assignation");
		else if ((destinyType.getTypeId() == TypeId.Object || destinyType.getTypeId() == TypeId.ObjectArray)
				&& !destinyType.equals(Type.stringType))
		{
			Symbol symbol = searchSymbol(destinyType.getName());
			
			if (symbol == null)
				errors.add(line + ": The class " + destinyType.getCompleteName() + " doesn't exist");
			else
				if (symbol.getSymbolType() != SymbolType.Class)
					errors.add(line + ": " + destinyType.getCompleteName() + " isn't a class name");
		}
		unaryExpr.testSemantic();
	}

	@Override
	public List<String> getSemanticErrors() {
		errors.addAll(unaryExpr.getSemanticErrors());
		return errors;
	}

	@Override
	public void emit(Formatter output) {
		unaryExpr.emit(output);
		if (destinyType.getTypeId() == TypeId.Primitive)
		{
			if (destinyType.equals(Type.intType) || destinyType.equals(Type.booleanType))
			{
				if (unaryExpr.getType().equals(Type.floatType))
					output.format("f2i\n");				
			}
			else
			{
				if (unaryExpr.getType().equals(Type.intType) || unaryExpr.getType().equals(Type.booleanType))
					output.format("i2f\n");
			}
		}
	}

	@Override
	public int getLine() {
		return line;
	}

	@Override
	public Type getType() {
		return destinyType;
	}

	@Override
	public void leftEmit(Formatter output) {}

}
